home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Milan_1991 / Devcon91.4 / AppShell / Examples / Skeleton / skeleton.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-01  |  18.1 KB  |  622 lines

  1. /*************************************************************************
  2.   *                                                                      *
  3.   *                            Preliminary                               *
  4.   *                        Amiga AppShell (tm)                           *
  5.   *                                                                      *
  6.   *  Copyright (c) 1990,1991 Commodore-Amiga, Inc. All Rights Reserved.  *
  7.   *                                                                      *
  8.   *   This software and information is proprietary, preliminary, and     *
  9.   *   subject to change without notice.                                  *
  10.   *                                                                      *
  11.   *                            DISCLAIMER                                *
  12.   *                                                                      *
  13.   *   THIS SOFTWARE IS PROVIDED "AS IS".                                 *
  14.   *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE      *
  15.   *   ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION      *
  16.   *   OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK.                 *
  17.   *   NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR     *
  18.   *   LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE.    *
  19.   *                                                                      *
  20.   *                          Non-Disclosure                              *
  21.   *                                                                      *
  22.   *   This information is not to be disclosed to any other company,      *
  23.   *   individual or party.  Discussion is to be restricted to CBM        *
  24.   *   approved discussion areas, such as the closed conferences on bix;  *
  25.   *   amiga.cert, amiga.com, amiga.beta/appshell.                        *
  26.   *                                                                      *
  27.   ************************************************************************
  28.   */
  29.  
  30. /* skeleton.c
  31.  * Copyright (C) 1991 Commodore-Amiga, Inc.
  32.  * Minimum requirements for an AppShell application.
  33.  * Written by David N. Junod
  34.  *
  35.  */
  36.  
  37. #include <exec/types.h>
  38. #include <exec/memory.h>
  39. #include <exec/libraries.h>
  40. #include <intuition/intuition.h>
  41. #include <graphics/gfx.h>
  42. #include <libraries/gadtools.h>
  43. #include <libraries/appshell.h>
  44. #include <utility/tagitem.h>
  45. #include <clib/alib_protos.h>
  46. #include <clib/alib_stdio_protos.h>
  47. #include <clib/exec_protos.h>
  48. #include <clib/intuition_protos.h>
  49. #include <clib/graphics_protos.h>
  50. #include <clib/gadtools_protos.h>
  51. #include <clib/appshell_protos.h>
  52. #include <clib/utility_protos.h>
  53. #include <pragmas/appshell_pragmas.h>
  54. #include <string.h>
  55.  
  56. #include "skeleton_rev.h"
  57.  
  58. /* The AppShell maintains some basic information on the application.  This
  59.  * information would appear in the About requester, and in AppExchange. */
  60. #define    APPBASE "SKELETON"
  61. #define    APPNAME "Skeleton"
  62. #define    APPVERS    VERS
  63. #define    APPCOPY "Copyright (C) 1991 Commodore-Amiga, Inc."
  64. #define    APPAUTH "David N. Junod"
  65.  
  66. STRPTR ver = VERSTAG;
  67.  
  68. /* This structure contains all the data that our application will need.
  69.  * Change to suit your application. */
  70. struct AppData
  71. {
  72.     UBYTE ad_TmpText[128];    /* Temporary text buffer */
  73.     LONG ad_Mode;        /* Output mode */
  74. };
  75.  
  76. /* Each public function gets a numeric ID assigned to it.  You must
  77.  * assign an ID to each one of your functions.  Look at appshell.h for
  78.  * standard function ID's for things like New, Open, Cut, Copy, Paste,
  79.  * Quit, etc... */
  80. #define DUMMYID        APSH_USER_ID
  81. #define CInitID        (DUMMYID + 1L)
  82. #define    OpenMainID    (DUMMYID + 2L)
  83. #define    SetModeID    (DUMMYID + 3L)
  84. #define    ErrorID        (DUMMYID + 4L)
  85. #define    GetInfoID    (DUMMYID + 5L)
  86. #define    User1ID        (DUMMYID + 6L)
  87. #define    User2ID        (DUMMYID + 7L)
  88. #define LAST_ID        (DUMMYID + 8L)
  89.  
  90.  
  91. /* These are the function prototypes for all the application implemented
  92.  * functions used in this example.  You must prototype all the functions
  93.  * that your application is going use in the function table. */
  94. VOID CInitFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  95. VOID OpenMainFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  96. VOID SetModeFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  97. VOID GetInfoFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  98. VOID ErrorFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  99. VOID QuitFunc (struct Hook *, struct AppInfo *, struct AppFunction *);
  100.  
  101. /* The AppShell will convert this array into function table entries and will
  102.  * add them to the function table list.  Using the APSHF_PRIVATE flag, we are
  103.  * able to have functions that can't be triggered by the user.  This
  104.  * also defines the commands that are available through ARexx.  Note that
  105.  * the command parser is case-INSENSITIVE, but for readability, your
  106.  * entries in this table should follow standard capitalization rules. */
  107. struct Funcs FTable[] =
  108. {
  109.     {"Quit", QuitFunc, QuitID,},
  110.     {"Error", ErrorFunc, ErrorID,},
  111.  
  112.  /* Functions with an argument template */
  113.     {"SetMode", SetModeFunc, SetModeID, "MALE/S,FEMALE/S,ZOMBIE/S", 3L, NULL,},
  114.     {"GetInfo", GetInfoFunc, GetInfoID, "STEM", 1L, NULL},
  115.  
  116.  /* These functions are private, and can not be accessed by the user */
  117.     {"CInit", CInitFunc, CInitID, NULL, NULL, APSHF_PRIVATE},
  118.     {"OpenMain", OpenMainFunc, OpenMainID, NULL, NULL, APSHF_PRIVATE},
  119.  
  120.  /* Experiment with ARexx scripts */
  121.     {"User1", NO_FUNCTION, User1ID, },
  122.     {"User2", NO_FUNCTION, User2ID, },
  123.  
  124.  /* Marks the end of the array */
  125.     {NULL, NO_FUNCTION,}
  126. };
  127.  
  128. /* All text used in the application must be defined in a text array.  Then
  129.  * referred to by numeric ID. */
  130. STRPTR Def_Text[] =
  131. {
  132.  /* Padding */
  133.     "",
  134.  
  135.  /* Window title */
  136.     "Skeleton",
  137. #define    TEXT_TITLE    1
  138.  
  139.     "Sex:",
  140. #define    TEXT_LABEL    2
  141.  
  142.  /* Main window menus */
  143. #define    TEXT_MENU    3
  144.     " TITLE PROJECT  LABEL Project",
  145.     "  ITEM QUIT     LABEL Quit                 KEY Q CMD Quit",
  146.  
  147.     " TITLE EXTRAS   LABEL Extras",
  148.     "  ITEM ERROR    LABEL \"Show Error...\"    KEY , CMD Error",
  149.     "  ITEM CMDSHELL LABEL \"Command Shell...\" KEY . CMD CmdShell",
  150.  
  151.     " TITLE USER     LABEL User",
  152.     "  ITEM USER1    LABEL \"Macro 1\"          KEY 1 CMD User1",
  153.     "  ITEM USER2    LABEL \"Macro 2\"          KEY 2 CMD User2",
  154.  
  155.     "   END",
  156.  
  157.     "Error: %s",
  158. #define    ERROR_DISPLAY    12
  159.  
  160.     "Can't send stem variable",
  161. #define    ERROR_CANT_RVI    13
  162.  
  163.  /* NULL termination is required */
  164.     NULL
  165. };
  166.  
  167.  
  168. /* The following four tag arrays are GadTool tags for Window Environment
  169.  * objects. */
  170. STRPTR output_data[] =
  171. {
  172.     "Male",
  173.     "Female",
  174.     "Zombie",
  175.     NULL
  176. };
  177.  
  178. struct TagItem output_tags[] =
  179. {
  180.     {GTCY_Labels, (LONG) output_data},
  181.     {TAG_DONE,}
  182. };
  183.  
  184. /* These are the objects that are going to be within our main window.
  185.  * Note that the window itself is an object, and receives the SAME name
  186.  * as in the WindowEnvironment tag list, APSH_NameTag.  If you want
  187.  * to specify any window tags, attach them to the window object. */
  188. struct Object objects[] =
  189. {
  190.     {&objects[1], 0, 0, OBJ_Window, NULL, NULL, NULL, "Main", TEXT_TITLE,
  191.      {0, 0, 0, 0}, NULL,},
  192.  
  193.     {NULL, 0, 0, OBJ_Cycle, SetModeID, NULL, NULL, "Mode", TEXT_LABEL,
  194.      {44, 4, 101, 16}, output_tags,},
  195. };
  196.  
  197. /* This is a Window Environment tag list.  It describes a window. */
  198. struct TagItem mainenv[] =
  199. {
  200.     {APSH_NameTag, (ULONG) "Main"},
  201.     {APSH_Objects, (ULONG) objects},
  202.     {APSH_TTMenu, TEXT_MENU},
  203.     {APSH_WinAOpen, OpenMainID},
  204.     {APSH_RefreshData, OpenMainID},
  205.     {APSH_CloseWindow, QuitID},
  206.     {TAG_DONE,}
  207. };
  208.  
  209. /* Shared system libraries */
  210. extern struct Library *SysBase;
  211. extern struct Library *DOSBase;
  212. struct Library *GadToolsBase;
  213. struct Library *GfxBase;
  214. struct Library *IconBase;
  215. struct Library *IntuitionBase;
  216. struct Library *UtilityBase;
  217. struct Library *MySpecialBase;
  218.  
  219. /* Library Environment:
  220.  * This tag array is used to open and close the shared system libraries
  221.  * needed by our application.
  222.  */
  223. struct TagItem Our_Libs[] =
  224. {
  225.  /* Minimum library version */
  226.     {APSH_LibVersion, 36L},
  227.  
  228.  /* All libraries are required */
  229.     {APSH_LibStatus, APSH_REQUIRED},
  230.  
  231.  /* Libraries to open */
  232.     {APSH_GadTools, (ULONG) & GadToolsBase},
  233.     {APSH_Gfx, (ULONG) & GfxBase},
  234.     {APSH_Icon, (ULONG) & IconBase},
  235.     {APSH_Intuition, (ULONG) & IntuitionBase},
  236.     {APSH_Utility, (ULONG) & UtilityBase},
  237.  
  238.  /* The next library is optional */
  239.     {APSH_LibStatus, APSH_OPTIONAL},
  240.     {APSH_LibName, (ULONG) "myspecial.library"},
  241.     {APSH_LibBase, (ULONG) & MySpecialBase},
  242.     {TAG_DONE,}
  243. };
  244.  
  245. /* Shell argument template */
  246. #define TEMPLATE "Male/S,Female/S,Zombie/S,PubScreen/K,PortName/K,Startup/K,NOGUI/S"
  247. #define OPT_MALE    0
  248. #define OPT_FEMALE    1
  249. #define    OPT_ZOMBIE    2
  250. #define    OPT_SCREENNAME    3
  251. #define    OPT_PORTNAME    4
  252. #define    OPT_STARTUP    5
  253. #define    OPT_NOGUI    6
  254. #define OPT_COUNT    7
  255.  
  256.  /* ARexx user interface environment specification array */
  257. struct TagItem Handle_AREXX[] =
  258. {
  259.     {APSH_Extens, (ULONG) "skel"},
  260.     {APSH_Rating, APSH_OPTIONAL},
  261.     {TAG_DONE,}
  262. };
  263.  
  264.  /* Command Shell user interface environment specification array */
  265. struct TagItem Handle_DOS[] =
  266. {
  267.  
  268.  /*
  269.   * Presence of this tag, makes the Command Shell to stay closed until the user
  270.   * sends a CMDSHELL OPEN command.
  271.   */
  272.     {APSH_Status, APSHP_INACTIVE},
  273.     {APSH_Rating, APSH_REQUIRED},
  274.     {TAG_DONE,}
  275. };
  276.  
  277. /* These tags describe the Intuition user interface. */
  278. struct TagItem Handle_IDCMP[] =
  279. {
  280.     {APSH_Rating, APSH_REQUIRED},
  281.     {TAG_DONE,}
  282. };
  283.  
  284. /* These tags describe the Simple IPC user interface. */
  285. struct TagItem Handle_SIPC[] =
  286. {
  287.     {APSH_Rating, APSH_REQUIRED},
  288.     {TAG_DONE,}
  289. };
  290.  
  291. /* Application Environment:
  292.  * Tell about our application */
  293. struct TagItem Our_App[] =
  294. {
  295.  /* About the application */
  296.     {APSH_AppName, (ULONG) APPNAME},
  297.     {APSH_AppVersion, (ULONG) APPVERS},
  298.     {APSH_AppCopyright, (ULONG) APPCOPY},
  299.     {APSH_AppAuthor, (ULONG) APPAUTH},
  300.  
  301.  /* Trigger the library opening module */
  302.     {APSH_OpenLibraries, (ULONG) Our_Libs},
  303.  
  304.  /* Specify the application function table */
  305.     {APSH_FuncTable, (ULONG) FTable},
  306.  
  307.  /* Specify the application text table */
  308.     {APSH_DefText, (ULONG) Def_Text},
  309.  
  310.  /* Tell how memory we need for our own data */
  311.     {APSH_UserDataSize, sizeof (struct AppData)},
  312.  
  313.  /* Give our Shell startup argument template */
  314.     {APSH_Template, (ULONG) TEMPLATE},
  315.     {APSH_NumOpts, (ULONG) OPT_COUNT},
  316.  
  317.  /* Must always specify the SIPC user interface */
  318.     {APSH_AddSIPC_UI, (ULONG) Handle_SIPC},
  319.  
  320.  /* Add an ARexx user interface */
  321.     {APSH_AddARexx_UI, (ULONG) Handle_AREXX},
  322.  
  323.  /* Add a Command Shell user interface */
  324.     {APSH_AddCmdShell_UI, (ULONG) Handle_DOS},
  325.  
  326.  /* Add an Intuition user interface */
  327.     {APSH_AddIntui_UI, (ULONG) Handle_IDCMP},
  328.  
  329.  /* Specify a custom initialization routine */
  330.     {APSH_AppInit, CInitID},
  331.  
  332.     {TAG_DONE,}
  333. };
  334.  
  335. extern struct Library *AppShellBase;
  336.  
  337. /* Handle messages between function handlers (this function is also
  338.  * defined in support/misc.c). */
  339. BOOL
  340. HandlerFunc (struct AppInfo * ai, ULONG tags,...)
  341. {
  342.  
  343.     return (HandlerFuncA (ai, (struct TagItem *) & tags));
  344. }
  345.  
  346.  /* Sample initialization function */
  347. VOID CInitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  348. {
  349.     extern struct TagItem mainenv[];
  350.     struct AppData *ad = ai->ai_UserData;
  351.  
  352.     /* See if any Shell arguments were specified */
  353.     if (ai->ai_Options[OPT_MALE])
  354.     {
  355.     ad->ad_Mode = 0L;
  356.     }
  357.     else if (ai->ai_Options[OPT_FEMALE])
  358.     {
  359.     ad->ad_Mode = 1L;
  360.     }
  361.     else if (ai->ai_Options[OPT_ZOMBIE])
  362.     {
  363.     ad->ad_Mode = 2L;
  364.     }
  365.  
  366.     /* Open the Main window */
  367.     HandlerFunc (ai,
  368.          APSH_Handler, "IDCMP",
  369.          APSH_Command, APSH_MH_OPEN,
  370.          APSH_WindowEnv, (ULONG) mainenv,
  371.          TAG_DONE);
  372. }
  373.  
  374. /* This function is called every time the Main window is opened.  It
  375.  * was specified by using the APSH_WinAOpen tag in the Main Window
  376.  * Environemt tag array.  I'm also 'cheating' and calling it everytime
  377.  * I want to refresh the window and graphics. */
  378.  
  379. VOID OpenMainFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  380. {
  381.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  382.     struct Window *win;
  383.     struct Gadget *gad;
  384.  
  385.     /* Update the mode gadget */
  386.     if (APSHGetGadgetInfo (ai, "Main", "Mode", (ULONG *) & win, (ULONG *) & gad))
  387.     {
  388.     /* Update the string gadget */
  389.     GT_SetGadgetAttrs (gad, win, NULL, GTCY_Active, ad->ad_Mode, TAG_DONE);
  390.     }
  391. }
  392.  
  393. VOID SetModeFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  394. {
  395.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  396.     struct TagItem *attrs = af->af_Attrs;
  397.     struct TagItem *tag;
  398.     struct Gadget *gad;
  399.     struct Window *win;
  400.     LONG mode = (-1);
  401.     struct Funcs *f;
  402.  
  403.     if (f = af->af_FE)
  404.     {
  405.     if (f->fe_Options[0])
  406.     {
  407.         ad->ad_Mode = mode = 0;
  408.     }
  409.     else if (f->fe_Options[1])
  410.     {
  411.         ad->ad_Mode = mode = 1;
  412.     }
  413.     else if (f->fe_Options[2])
  414.     {
  415.         ad->ad_Mode = mode = 2;
  416.     }
  417.     }
  418.     /* Being set from the gadget */
  419.     else if (tag = FindTagItem (APSH_MsgCode, attrs))
  420.     {
  421.     ad->ad_Mode = tag->ti_Data;
  422.     }
  423.  
  424.     /* Update the gadget */
  425.     if ((mode >= 0) &&
  426.     (APSHGetGadgetInfo (ai, "Main", "Mode", (ULONG *) & win, (ULONG *) & gad)))
  427.     {
  428.     /* Update the string gadget */
  429.     GT_SetGadgetAttrs (gad, win, NULL, GTCY_Active, mode, TAG_DONE);
  430.     }
  431. }
  432.  
  433.  /* sample function returning an error */
  434. VOID ErrorFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  435. {
  436.     STRPTR name = "Uh Oh!";
  437.  
  438.     /* sample error return */
  439.     ai->ai_Pri_Ret = RETURN_ERROR;
  440.     ai->ai_Sec_Ret = ERROR_DISPLAY;
  441.     ai->ai_TextRtn = PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, (int) name);
  442. }
  443.  
  444. /* Given a screen pointer, determine the public screen name */
  445. VOID PubScreenName (struct Screen * scr, STRPTR buffer)
  446. {
  447.     struct Screen *cs = NULL;
  448.     struct List *publist;
  449.     struct List copy_publist;
  450.     struct PubScreenNode *psnode;
  451.     struct PubScreenNode *copy_psnode;
  452.  
  453.     /* Initialize our variables */
  454.     strcpy (buffer, "<private>");
  455.     NewList (©_publist);
  456.  
  457.     /* Lock the public screen list */
  458.     publist = LockPubScreenList ();
  459.  
  460.     /* and copy it */
  461.     for (psnode = (struct PubScreenNode *) publist->lh_Head;
  462.      psnode->psn_Node.ln_Succ;
  463.      psnode = (struct PubScreenNode *) psnode->psn_Node.ln_Succ)
  464.     {
  465.     if (copy_psnode = AllocMem (sizeof (struct PubScreenNode), MEMF_CLEAR))
  466.     {
  467.         /* Copy the structure */
  468.         *copy_psnode = *psnode;
  469.  
  470.         /*
  471.          * ln_Name points to the public screen name, make your own copy
  472.          */
  473.         if (copy_psnode->psn_Node.ln_Name = AllocMem (strlen (psnode->psn_Node.ln_Name) + 1, MEMF_CLEAR))
  474.         {
  475.         strcpy (copy_psnode->psn_Node.ln_Name, psnode->psn_Node.ln_Name);
  476.         }
  477.  
  478.         AddTail (©_publist, (struct Node *) copy_psnode);
  479.     }
  480.     }
  481.  
  482.     UnlockPubScreenList ();
  483.  
  484.     psnode = (struct PubScreenNode *) copy_publist.lh_Head;
  485.     while ((copy_psnode = (struct PubScreenNode *) psnode->psn_Node.ln_Succ) &&
  486.        (cs == NULL))
  487.     {
  488.     if (psnode->psn_Screen == scr)
  489.     {
  490.         strcpy (buffer, psnode->psn_Node.ln_Name);
  491.         cs = psnode->psn_Screen;
  492.     }
  493.  
  494.     if (psnode->psn_Node.ln_Name)
  495.     {
  496.         FreeMem (psnode->psn_Node.ln_Name, strlen (psnode->psn_Node.ln_Name) + 1);
  497.     }
  498.     Remove ((struct Node *) psnode);
  499.     FreeMem (psnode, sizeof (struct PubScreenNode));
  500.     psnode = copy_psnode;
  501.     }
  502. }
  503.  
  504. /* sample function returning ARexx stem variables */
  505. VOID GetInfoFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  506. {
  507.     /* ARexx function prototypes */
  508.     extern LONG SetRexxVar (struct RexxMsg *, UBYTE *, UBYTE *, LONG);
  509.     extern LONG CheckRexxMsg (struct RexxMsg *);
  510.  
  511.     struct AppData *ad = (struct AppData *) ai->ai_UserData;
  512.     UBYTE stem[128], value[140];
  513.     struct MsgHandler *mh;
  514.     struct RexxMsg *msg;
  515.     struct Funcs *f;
  516.     LONG kind;
  517.  
  518.     /* Build error string */
  519.     ai->ai_Pri_Ret = RETURN_WARN;
  520.     ai->ai_Sec_Ret = ERROR_CANT_RVI;
  521.     ai->ai_TextRtn = PrepText (ai, APSH_USER_ID, ai->ai_Sec_Ret, NULL);
  522.  
  523.     /* Find out what type the current message is */
  524.     if (GetAPSHAttr (ai, APSH_ActvMH, ai, &kind))
  525.     {
  526.     /* See if the current message is an ARexx message */
  527.     if (kind == APSH_AREXX_ID)
  528.     {
  529.         /* Get a pointer to the current message */
  530.         if (GetAPSHAttr (ai, APSH_ActvMessage, ai, &msg))
  531.         {
  532.         /* Check to see if we can set an RVI on this message. */
  533.         if (CheckRexxMsg (msg))
  534.         {
  535.             /* Get the destination stem name */
  536.             sprintf (stem, "%s.", ai->ai_BaseName);
  537.             if (f = af->af_FE)
  538.             {
  539.             if (f->fe_Options[0])
  540.             {
  541.                 strcpy (stem, (STRPTR) f->fe_Options[0]);
  542.             }
  543.             }
  544.  
  545.         /* Send the application version */
  546.  
  547.             /* Build the version variable */
  548.             sprintf (ad->ad_TmpText, "%sVERSION", stem);
  549.             strcpy (value, ai->ai_AppVersion);
  550.  
  551.             /* Set the RVI's */
  552.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  553.  
  554.         /* Send the current public screen name */
  555.  
  556.             /* Build the screen name variable */
  557.             value[0] = 0;
  558.             sprintf (ad->ad_TmpText, "%sSCREEN", stem);
  559.             if (ai->ai_ScreenName)
  560.             {
  561.             strcpy (value, ai->ai_ScreenName);
  562.             }
  563.             else
  564.             {
  565.             PubScreenName (ai->ai_Screen, value);
  566.             }
  567.  
  568.             /* Set the RVI's */
  569.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  570.  
  571.         /* Send the ARexx port name */
  572.  
  573.             /* Build the ARexx port name variable */
  574.             sprintf (ad->ad_TmpText, "%sAREXX", stem);
  575.  
  576.             /* Build the value string */
  577.             strcpy (value, "<unnamed>");
  578.             if (GetAPSHAttr (ai, APSH_ARexxMH, ai, &mh) && mh)
  579.             {
  580.             strcpy (value, mh->mh_PortName);
  581.             }
  582.  
  583.             /* Set the RVI's */
  584.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  585.  
  586.         /* Send the current mode */
  587.  
  588.             /* Build the variable name */
  589.             sprintf (ad->ad_TmpText, "%sMODE", stem);
  590.  
  591.             /* Build the value string */
  592.             strcpy (value, "<unset>");
  593.             if (ad->ad_Mode == 0)
  594.             strcpy (value, "Male");
  595.             else if (ad->ad_Mode == 1)
  596.             strcpy (value, "Female");
  597.             else if (ad->ad_Mode == 2)
  598.             strcpy (value, "Zombie");
  599.  
  600.             /* Set the RVI's */
  601.             SetRexxVar (msg, ad->ad_TmpText, value, strlen (value));
  602.  
  603.         /* Return the name of the destination stem variable */
  604.  
  605.             /* Let them know what the stem variable is named */
  606.             strcpy (ad->ad_TmpText, stem);
  607.             ai->ai_Pri_Ret = RETURN_OK;
  608.             ai->ai_Sec_Ret = NULL;
  609.             ai->ai_TextRtn = ad->ad_TmpText;
  610.         }
  611.         }
  612.     }
  613.     }
  614. }
  615.  
  616.  /* Shutdown routine */
  617. VOID QuitFunc (struct Hook *h, struct AppInfo *ai, struct AppFunction *af)
  618. {
  619.     /* Tell the AppShell that we're all done now. */
  620.     ai->ai_Done = TRUE;
  621. }
  622.